﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  JoinNowOfferAnswer.cs
//    
// Abstract:
//
// Implements the signaling session IOfferAnswer interface for media negotiation for
// joining a conference.
//  
//--

using System;
using System.Diagnostics;
using System.IO;
using System.Net.Mime;
using System.Text;
using System.Xml;
using Microsoft.Rtc.Signaling;

namespace Microsoft.EnhancedReminders.Dispatcher.Workflow
{
    /// <summary>
    /// Implements IOfferAnswer to specify the conferencing URI.
    /// </summary>
    public class JoinNowOfferAnswer : IOfferAnswer
    {
        #region Constants

        private const string Audio = "audio";
        private const string Available = "available";
        private const string Conferencing = "Conferencing";
        private const string ContentTypeConferenceInviteXml = "application/ms-conf-invite+xml";
        private const string Data = "data";
        private const string FocusUri = "focus-uri";
        private const string Subject = "subject";
        private const string True = "true";
        private const string Version = "version";

        #endregion

        private static ContentType ApplicationConfInviteXmlContent = new ContentType(ContentTypeConferenceInviteXml);

        #region Privates

        private string _conferenceAddress;
        private string _subject;
        private bool _isLiveMeeting;
        
        #endregion

        #region IOfferAnswer Members

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="joinNowInfo">Conference information for the join now session.</param>
        internal JoinNowOfferAnswer(ConferencingInformation joinNowInfo)
        {
            Debug.Assert(joinNowInfo != null, "joinNowInfo");
            Debug.Assert(joinNowInfo._notificationItem != null, "joinNowInfo._notificationItem");
            Debug.Assert(!String.IsNullOrEmpty(joinNowInfo._notificationItem.Message), "!String.IsNullOrEmpty(joinNowInfo._notificationItem.Message)");
            Debug.Assert(joinNowInfo._notificationItem.ReminderItem != null, "joinNowInfo._notificationItem.ReminderItem");
            Debug.Assert(!String.IsNullOrEmpty(joinNowInfo._notificationItem.ReminderItem.ConferenceAddress), "!String.IsNullOrEmpty(joinNowInfo._notificationItem.ReminderItem.ConferenceAddress)");

            _conferenceAddress = joinNowInfo._notificationItem.ReminderItem.ConferenceAddress;
            _subject = joinNowInfo._notificationItem.Message;
            _isLiveMeeting = joinNowInfo.IsLiveMeeting;
        }

        /// <summary>
        /// Returns ContentDescription that was offered.
        /// </summary>
        /// <param name="sender">Sender of the ContentDescription.</param>
        /// <param name="offer">ContentDescription being offered by the target endpoint.</param>
        /// <returns>ContentDescription offered in return.</returns>
        public ContentDescription GetAnswer(object sender, ContentDescription offer)
        {
            Debug.Assert(sender != null, "sender != null");
            Debug.Assert(offer != null, "offer != null");

            return offer;
        }

        /// <summary>
        /// Returns the content description for the join now invite.
        /// </summary>
        /// <param name="sender">Remote endpoint</param>
        /// <returns>A ContentDescription object with an embedded XML</returns>
        public ContentDescription GetOffer(object sender)
        {
            Debug.Assert(sender != null, "sender != null");

            ContentDescription result = null;

            using (MemoryStream stream = new MemoryStream())
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Encoding = Encoding.ASCII;
                settings.OmitXmlDeclaration = true;
                settings.Indent = true;

                using (XmlWriter writer = XmlWriter.Create(stream, settings))
                {
                    writer.WriteStartElement(Conferencing);
                    writer.WriteAttributeString(Version, "2.0");

                    // <focus-uri></focus-uri>
                    writer.WriteElementString(FocusUri, _conferenceAddress);

                    // <subject></subject>
                    writer.WriteElementString(Subject, _subject);

                    if (_isLiveMeeting) // If this is a Live Meeting, we're sharing data.
                    {
                        writer.WriteStartElement(Data);
                        writer.WriteAttributeString(Available, True);
                        writer.WriteEndElement();
                    }
                    else // Otherwise, for a Conference Call, we're sharing audio.
                    {
                        writer.WriteStartElement(Audio);
                        writer.WriteAttributeString(Available, True);
                        writer.WriteEndElement();
                    }

                    // </Conferencing>

                    writer.WriteEndElement();
                    writer.Flush();
                    writer.Close();
                }

                result = new ContentDescription(ApplicationConfInviteXmlContent, stream.ToArray());
            }

            Debug.Assert(result != null, "result != null");
            return result;
        }

        /// <summary>
        /// Offered by remote endpoint in its response to the invite. 
        /// </summary>
        /// <param name="sender">Remote endpoint</param>
        /// <param name="e">ContentDescription offered by remote endpoint in its response to the invite</param>
        /// <remarks>Ignored</remarks>
        public void HandleOfferInInviteResponse(object sender, OfferInInviteResponseEventArgs e)
        {
            Debug.Assert(sender != null, "sender != null");
            Debug.Assert(e != null, "e != null");
        }

        /// <summary>
        /// Content description offered by remote endpoint in its re-invite
        /// </summary>
        /// <param name="sender">Remote endpoint</param>
        /// <param name="e">ContentDescription offered by remote endpoint</param>
        /// <remarks>Ignored</remarks>
        public void HandleOfferInReInvite(object sender, OfferInReInviteEventArgs e)
        {
            Debug.Assert(sender != null, "sender != null");
            Debug.Assert(e != null, "e != null");
        }

        /// <summary>
        /// Response by remote endpoint to the Content Description offered
        /// </summary>
        /// <param name="sender">Remote endpoint</param>
        /// <param name="answer">Answer to our offer. Can be null</param>
        /// <remarks>Ignored</remarks>
        public void SetAnswer(object sender, ContentDescription answer)
        {
            Debug.Assert(sender != null, "sender != null");
        }

        #endregion
    }
}
